/* eslint-disable @typescript-eslint/no-explicit-any */
import { _decorator, Component, UITransform, EventTouch, v3, Node } from 'cc';
import { FlyTipsPanel } from './FlyTipsPanel';
import { TipsObjectType, TipsDataBase, MinWinTips, DropDownListData } from './TipsDataBase';
import { PoolFactory } from '../../Component/PoolFactory';
import { DropdownList } from './comp/DropdownList';
import { GameManager } from '../../Manager/GameManager';
import { Tool } from '../../../Util/Tool';
import { NodeRecycle } from '../../Manager/PoolManager';

const { ccclass, property } = _decorator;

@ccclass('TipsManager')
export class TipsManager extends Component {
  static Singleton: TipsManager;

  @property(PoolFactory)
  factory: PoolFactory = null!;
  @property(FlyTipsPanel)
  flyTipsPanel: FlyTipsPanel = null!;

  /** 不穿透,点击取消的区域 */
  private canelArea: UITransform[] = [];
  /** 不可穿透的区域 */
  private freeArea: UITransform[] = [];
  /** 触发点击的节点 */
  private controlNode: string = '';
  /** 可以触发点击的tip有且只有一个 */
  private curTip: Node;
  private tipsType: TipsObjectType;

  constructor() {
    super();
    TipsManager.Singleton = this;
  }

  setTipClick() {
    this.node.on(Node.EventType.TOUCH_START, this.onClickPanel, this);
    this.node.on(Node.EventType.TOUCH_MOVE, this.onCanel, this);
    this.node.on(Node.EventType.TOUCH_CANCEL, this.onCanel, this);
    this.node.on(Node.EventType.TOUCH_END, this.onCanel, this);
  }

  removeTipClick() {
    this.node.off(Node.EventType.TOUCH_START, this.onClickPanel, this);
    this.node.off(Node.EventType.TOUCH_MOVE, this.onCanel, this);
    this.node.off(Node.EventType.TOUCH_CANCEL, this.onCanel, this);
    this.node.off(Node.EventType.TOUCH_END, this.onCanel, this);
    this.freeArea.length = 0;
    this.canelArea.length = 0;
    this.tipsType = null;
  }

  onClickPanel(event: EventTouch) {
    if (this.canelArea.length > 0 && this.curTip != null) {
      const clickPos = event.getUILocation();
      const pos = v3(clickPos.x, clickPos.y);
      const temp = v3();
      let boo = false;
      for (let i = 0; i < this.canelArea.length; i++) {
        const area = this.canelArea[i];
        area.convertToNodeSpaceAR(pos, temp);
        if (Tool.judgePointInArea(area, temp)) {
          boo = true;
          break;
        }
      }
      if (boo) {
        this.canelTip();
        return;
      }
    }
    event.preventSwallow = true;
    if (this.freeArea != null && this.curTip != null) {
      const clickPos = event.getUILocation();
      const pos = v3(clickPos.x, clickPos.y);
      const temp = v3();
      let boo = false;
      for (let i = 0; i < this.freeArea.length; i++) {
        const area = this.freeArea[i];
        temp.set(pos.x, pos.y);
        if (Tool.judgePointInArea(area, temp)) {
          boo = true;
          break;
        }
      }
      if (boo) {
        // console.log('click free');
        return;
      }
    }
    this.canelTip();
  }

  private onCanel(event: EventTouch) {
    event.preventSwallow = true;
  }

  private releaseCurTip() {
    if (!this.curTip) return;
    const sp: NodeRecycle = this.curTip.getComponent(NodeRecycle as any);
    if (sp) {
      sp.release();
    } else {
      this.curTip.active = false;
    }
    this.curTip = null;
  }

  canelTip() {
    switch (this.tipsType) {
      case TipsObjectType.miniWinTips:
        this.removeTipClick();
        break;
      case TipsObjectType.dropdownList:
        this.removeTipClick();
        break;
      default:
        break;
    }
    this.controlNode = '';
    this.releaseCurTip();
    this.tipsType = null;
  }

  showTips(data: TipsDataBase) {
    if (this.tipsType && this.tipsType != data.className) {
      this.canelTip();
    }
    switch (data.className) {
      case TipsObjectType.miniWinTips:
        this.shopMinWinTip(data as MinWinTips);
        data.release();
        break;
      case TipsObjectType.dropdownList:
        this.shopDropdownList(data as DropDownListData);
        data.release();
        break;
      default:
        this.flyTipsPanel.flyTips(data);
        break;
    }
    this.tipsType = data.className;
  }

  private shopMinWinTip(data: MinWinTips) {
    if (this.curTip) {
      if (data.controler != this.controlNode) {
        this.releaseCurTip();
        this.freeArea.length = 0;
        this.canelArea.length = 0;
      } else {
        this.canelTip();
        return;
      }
    } else {
      this.setTipClick();
    }
    this.curTip = data.node;
    this.canelArea = data.canelForm;
    this.freeArea = data.form;
    this.curTip.active = true;
  }

  private shopDropdownList(data: DropDownListData) {
    if (this.curTip) {
      if (data.controler != this.controlNode) {
        this.releaseCurTip();
        this.freeArea.length = 0;
        this.canelArea.length = 0;
      } else {
        return;
      }
      const sp: DropdownList = this.curTip.getComponent(DropdownList);
      sp.reuse(data);
    } else {
      this.curTip = this.factory.pop(TipsObjectType.dropdownList, data);
      this.setTipClick();
    }
    this.controlNode = data.controler;
    const area = data.node.getComponent(UITransform);
    this.freeArea = [area, this.curTip.getComponent(UITransform), ...data.area];
    const pos = GameManager.Singleton.getUIWorldPosition(data.node);
    pos.x -= area.width * area.anchorX;
    pos.y -= area.height * area.anchorY;
    this.curTip.setPosition(pos);
    this.node.insertChild(this.curTip, 0);
  }

  changeDropdownData(text: string) {
    if (this.tipsType != TipsObjectType.dropdownList) return;
    const sp: DropdownList = this.curTip.getComponent(DropdownList);
    sp.onChange(text);
  }
}
